import 'dart:ui';
import 'package:get/state_manager.dart';

import 'sea_mooeen_controller.dart';

import 'package:flutter/material.dart';

class SeaMoonPage extends StatelessWidget {
  SeaMoonPage({Key? key}) : super(key: key);
  final SeaMooenController controller = SeaMooenController();

  @override
  Widget build(BuildContext context) {
    return GetBuilder<SeaMooenController>(
      init: controller,
      builder: (store) => CustomPaint(
        child: null,
        painter: StarPainter(
          moonCenterY: store.seaLevel,
          starPositions: store.starPositions,
          starSizes: store.starSizes,
          blinkIndexes: store.blinkIndexes,
        ),
        foregroundPainter: MoonPainter(
          moonCenterY: store.moonCenterY,
          seaLevel: store.seaLevel,
          waveY: store.waveY,
          waveRadius: store.waveRadius,
          wingHeight: store.wingHeight,
          birdFlyDistance: store.birdFlyDistance,
        ),
      ),
    );
  }
}

class StarPainter extends CustomPainter {
  final double moonCenterY;
  final List<Offset> starPositions;
  final List<double> starSizes;
  final List<bool> blinkIndexes;
  StarPainter({
    required this.moonCenterY,
    required this.starPositions,
    required this.starSizes,
    required this.blinkIndexes,
  }) : super();
  @override
  void paint(Canvas canvas, Size size) {
    paintStar(canvas, size);
  }

  void paintStar(Canvas canvas, Size size) {
    // if (blink) {
    //   starColor = starColor!.withAlpha(200);
    // }
    var starColor;

    var starPaint = Paint();
    starPaint.strokeWidth = 2.0;

    int index = 0;
    starPositions.forEach((center) {
      double centerX = center.dx;
      double centerY = center.dy;
      double offset = starSizes[index];
      double radius = offset - 0.5;
      starColor = Colors.yellow[50];
      if (blinkIndexes[index]) {
        starColor = starColor!.withAlpha(190);
      }
      starPaint..color = starColor;

      Path starPath = Path();
      starPath.moveTo(centerX, centerY - offset);
      starPath.arcToPoint(Offset(centerX - offset, centerY),
          radius: Radius.circular(radius));
      starPath.arcToPoint(Offset(centerX, centerY + offset),
          radius: Radius.circular(radius));
      starPath.arcToPoint(Offset(centerX + offset, centerY),
          radius: Radius.circular(radius));
      starPath.arcToPoint(Offset(centerX, centerY - offset),
          radius: Radius.circular(radius));
      canvas.drawPath(starPath, starPaint);
      index++;
    });
  }

  @override
  bool shouldRepaint(covariant CustomPainter oldDelegate) {
    return true;
  }
}

class MoonPainter extends CustomPainter {
  final double moonCenterY;
  final double seaLevel;
  final double waveY;
  final double waveRadius;
  final double wingHeight;
  final double birdFlyDistance;
  MoonPainter({
    required this.moonCenterY,
    required this.seaLevel,
    required this.waveY,
    required this.waveRadius,
    required this.wingHeight,
    required this.birdFlyDistance,
  }) : super();

  @override
  void paint(Canvas canvas, Size size) {
    canvas.drawColor(
        Color(0xFF252525)
            .withAlpha(250 - (moonCenterY / size.height * 255).toInt()),
        BlendMode.color);
    var center = size / 2;
    paintMooen(canvas, Offset(center.width, moonCenterY), 90);
    for (var i = 0; i < 5; ++i) {
      double step = (5.0 - i) * 15;
      paintBird(
          canvas,
          Offset(birdFlyDistance + step,
              seaLevel + 100 - birdFlyDistance * 2 - step),
          wingHeight,
          radius: 20.0 + 2 * i,
          wingSize: 22.0 + 2 * i);
    }

    paintSea(canvas, size);

    paintPoet(canvas, '但愿人长久 千里共婵娟', size);
  }

  void paintMooen(Canvas canvas, Offset center, double raidus) {
    var mooenPaint = Paint()..color = Colors.yellow[100]!;
    mooenPaint.strokeWidth = 2.0;
    canvas.drawCircle(
      center,
      raidus,
      mooenPaint,
    );

    var lightPaint = Paint()..color = Colors.yellow[100]!.withAlpha(30);
    lightPaint.strokeWidth = 2.0;
    canvas.drawCircle(
      center,
      raidus + 3,
      lightPaint,
    );
  }

  void paintBird(Canvas canvas, Offset center, double wingHeight,
      {double radius = 28, double wingSize = 32}) {
    var birdPaint = Paint()..color = Colors.black;
    birdPaint.strokeWidth = 2.0;
    double wingRadiusDiff = 3.0;
    Path leftPath = Path();

    leftPath.moveTo(center.dx - wingSize, center.dy - wingHeight);
    leftPath
      ..arcToPoint(Offset(center.dx, center.dy),
          radius: Radius.circular(radius), clockwise: true);
    leftPath.arcToPoint(Offset(center.dx - wingSize, center.dy - wingHeight),
        radius: Radius.circular(radius - wingRadiusDiff), clockwise: false);
    canvas.drawPath(leftPath, birdPaint);
    Path rightPath = Path();
    rightPath.moveTo(center.dx + wingSize, center.dy - wingHeight);
    rightPath
      ..arcToPoint(Offset(center.dx, center.dy),
          radius: Radius.circular(radius), clockwise: false);
    rightPath.arcToPoint(Offset(center.dx + wingSize, center.dy - wingHeight),
        radius: Radius.circular(radius - wingRadiusDiff), clockwise: true);
    canvas.drawPath(rightPath, birdPaint);
  }

  void paintSea(Canvas canvas, Size size) {
    var seaPaint = Paint()..color = Color(0xFF020408);
    seaPaint.strokeWidth = 2.0;
    Path backPath = Path();
    backPath.moveTo(0, seaLevel);
    int backCount = 6;
    for (var i = 0; i < backCount + 1; ++i) {
      if (i % 2 == 0) {
        backPath.arcToPoint(
            Offset(size.width / backCount + i * size.width / backCount,
                seaLevel + waveY),
            radius: Radius.circular(waveRadius));
      } else {
        backPath.arcToPoint(
            Offset(size.width / backCount + i * size.width / backCount,
                seaLevel + waveY),
            radius: Radius.circular(waveRadius),
            clockwise: false);
      }
    }
    backPath.lineTo(size.width, size.height);
    backPath.lineTo(0, size.height);
    canvas.drawPath(backPath, seaPaint);

    Path middlePath = Path();
    middlePath.moveTo(size.width, seaLevel);
    int middleWaveCount = 4;
    for (var i = 1; i < middleWaveCount + 1; ++i) {
      if (i % 2 == 0) {
        middlePath.arcToPoint(
            Offset(size.width - i * size.width / middleWaveCount,
                seaLevel - waveY),
            radius: Radius.circular(waveRadius),
            clockwise: false);
      } else {
        middlePath.arcToPoint(
            Offset(size.width - i * size.width / middleWaveCount,
                seaLevel - waveY),
            radius: Radius.circular(waveRadius),
            clockwise: true);
      }
    }
    middlePath.lineTo(0, size.height);
    middlePath.lineTo(size.width, size.height);

    canvas.drawPath(middlePath, seaPaint);

    Path frontPath = Path();
    frontPath.moveTo(0, seaLevel);
    int frondCount = 8;
    for (var i = 0; i < frondCount + 1; ++i) {
      if (i % 2 == 0) {
        frontPath.arcToPoint(
            Offset(size.width / frondCount + i * size.width / frondCount,
                seaLevel + waveY + 10),
            radius: Radius.circular(waveRadius),
            clockwise: false);
      } else {
        frontPath.arcToPoint(
            Offset(size.width / frondCount + i * size.width / frondCount,
                seaLevel + waveY + 10),
            radius: Radius.circular(waveRadius),
            clockwise: true);
      }
    }
    frontPath.lineTo(size.width, size.height);
    frontPath.lineTo(0, size.height);
    canvas.drawPath(frontPath, seaPaint);
  }

  void paintPoet(Canvas canvas, String poet, Size size) {
    var style = TextStyle(
      fontWeight: FontWeight.w300,
      fontSize: 26.0,
      color: Colors.yellow[100],
    );

    final ParagraphBuilder paragraphBuilder = ParagraphBuilder(
      ParagraphStyle(
        fontSize: style.fontSize,
        fontFamily: style.fontFamily,
        fontStyle: style.fontStyle,
        fontWeight: style.fontWeight,
        textAlign: TextAlign.center,
      ),
    )
      ..pushStyle(style.getTextStyle())
      ..addText(poet);
    final Paragraph paragraph = paragraphBuilder.build()
      ..layout(ParagraphConstraints(width: size.width));
    canvas.drawParagraph(paragraph, Offset(0, 100));
  }

  @override
  bool shouldRepaint(covariant CustomPainter oldDelegate) {
    return true;
  }
}
